function getObj<T extends object>(obj: T) { 
  return obj;
}

getObj({ id: 1, name: "aaa" });

type ObjLength = {
  length: number
}

function getObjLength<T extends ObjLength>(obj: T) { 
  // todos...
  return obj;
}

getObjLength("aaaa");
getObjLength([1, 2, 3, 4, 5]);
getObjLength({ id: 1, name: "jack", length: 3 });

// 封装一个函数，函数的两个参数的长度相减，获取长度的差
function compareLength<T extends ObjLength, U extends ObjLength>(a:T, b:U) { 
  return a.length - b.length;
}

const result = compareLength([2, 3, 4, 5, 6], "abc");
console.log(result);


type TreeNode = {
  value:string
}

type LeafNode = TreeNode & {
  isLeaf: true
}

type InnerNode = TreeNode & {
  children:TreeNode[]
}

const a: TreeNode = { value: "a" };
const b: LeafNode = { value: "b", isLeaf:true };
const c: LeafNode = { value: "c", isLeaf:true };
const d: InnerNode = { value: "d", children: [b, c] };

function mapNode<T extends TreeNode>(node:T, f:(value:string)=>string) { 
  return {
    ...node,
    value: f(node.value)
  }
}

const a1 = mapNode(a, (v) => v.toUpperCase());
const b1 = mapNode(b, (v) => v.toUpperCase());
const c1 = mapNode(c, (v) => v.toUpperCase());
const d1 = mapNode(d, (v) => v.toUpperCase());

console.log(a1)
console.log(b1)
console.log(c1)
console.log(d1)


// 方括号运算符,同样可以作用于泛型当中
// type User = {
//   id: number,
//   name: string,
//   sex:"男" | "女"
// }

// type A = User['sex'];


type Message<T extends { message: unknown }> = T['message'];
const person = {
  id: 1,
  message:"hello"
}

type B = typeof person

// type Person = {
//   id: number,
//   message: string
// }

type PersonMessage = Message<B>

// 元组类型的推导
// const arr = [1,true];
const arr = [1, true] as const

// function myTuple<T>(...ts: T[]) { 
//   return ts
// }

// const t = myTuple(1, 2, 3, 4);

function myTuple<T extends any[]>(...ts: T) { 
  return ts;
}

const t = myTuple(1, 2, 3, 4, 5);

const t2 = myTuple(1, "aa", true);

const t3 = myTuple(...["admin", "user", "client"]);


